package cn.concurrent.utlis;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: lz
 * @Date: 2018/8/31 17:01
 * @Version 1.0
 */
public class CyclicBarrierDemo {
	/**
	 * 开运动会时，会有跑步这一项运动，我们来模拟下运动员入场时的情况，假设有6条跑道，
	 * 在比赛开始时，就需要6个运动员在比赛开始的时候都站在起点了，裁判员吹哨后才能开始
	 * 跑步。跑道起点就相当于“barrier”，是临界点，而这6个运动员就类比成线程的话，就是
	 * 这6个线程都必须到达指定点了，意味着凑齐了一波，然后才能继续执行，否则每个线程都
	 * 得阻塞等待，直至凑齐一波即可。cyclic是循环的意思，也就是说CyclicBarrier当多个
	 * 线程凑齐了一波之后，仍然有效，可以继续凑齐下一波
	 */
	//指定必须有6个运动员到达才行
	private static CyclicBarrier barrier = new CyclicBarrier(6, () -> {
		System.out.println("所有运动员入场，裁判员一声令下！！！！！");
	});
	public static void main(String[] args) {
		System.out.println("运动员准备进场，全场欢呼............");

		ExecutorService service = Executors.newFixedThreadPool(6);
		for (int i = 0; i < 6; i++) {
			service.execute(() -> {
				try {
					System.out.println(Thread.currentThread().getName() + " 运动员，进场");
					barrier.await();
					System.out.println(Thread.currentThread().getName() + "  运动员出发");
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (BrokenBarrierException e) {
					e.printStackTrace();
				}
			});
		}
	}
	/**
	 * CountDownLatch与CyclicBarrier都是用于控制并发的工具类，都可以理解成维护的就是一个计数器，但是这两者还是各有不同侧重点的：
	 *
	 * CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后，它才执行；而CyclicBarrier一般用于一组线程互相等待至某个
	 * 状态，然后这一组线程再同时执行；CountDownLatch强调一个线程等多个线程完成某件事情。CyclicBarrier是多个线程互等，等大家都
	 * 完成，再携手共进。
	 * 调用CountDownLatch的countDown方法后，当前线程并不会阻塞，会继续往下执行；而调用CyclicBarrier的await方法，会阻塞当前线程，
	 * 直到CyclicBarrier指定的线程全部都到达了指定点的时候，才能继续往下执行;CountDownLatch方法比较少，操作比较简单，
	 * 而CyclicBarrier提供的方法更多，比如能够通过getNumberWaiting()，isBroken()这些方法获取当前多个线程的状态，并且CyclicBarrier
	 * 的构造方法可以传入barrierAction，指定当所有线程都到达时执行的业务功能；CountDownLatch是不能复用的，而CyclicLatch是可以复用的。
	 *
	 */

}
